#include "tcpServer.hpp"
#include <memory>
// #include "commandExe.hpp"
#include "protocol.hpp"
#include "calculator.hpp"
#include "Deamon.hpp"
#include <functional>

using namespace LogModule;
// zdl:: package 一定就会有完整的报文呢
// * 完整 -》 提取 -》 反序列化 -》 计算模块，进行处理
// * 不完整 -》 继续处理
using cal_fun = std::function<Response(const Request &req)>;
class Parse
{
public:
    Parse(cal_fun c) : _cal(c)
    {
    }
    std::string Entrance(std::string &package)
    {
        // 1. 判断报文的完整性
        std::string message;
        std::string respstr;

        while (Decode(package, &message))
        {
            LOG(LogLevel::DEBUG) << "Content: \n"
                                 << message;
            if (message.empty())
                break;
            // 2. 反序列化
            Request req;
            if (!req.Deserialize(message))
                break;
            std::cout << "##############" << std::endl;
            req.print();
            std::cout << "##############" << std::endl;
            // 3. 计算
            Response resp = _cal(req);
            // 4. 序列化
            std::string res;
            resp.Serialize(res);

            LOG(LogLevel::DEBUG) << "序列化: \n"
                                 << res;
            // 5. 添加报头
            Encode(res);
            LOG(LogLevel::DEBUG) << "Encode: \n"
                                 << res;
            // 6. 凭借应答
            respstr += res;
        }
        LOG(LogLevel::DEBUG) << "respstr: \n" << respstr;
        return respstr;
    }

private:
    cal_fun _cal;
};

int main()
{
    ENABLE_FILE_LOG();
    // Command cmd;
    // std::unique_ptr<tcpServer> tsvr = std::make_unique<tcpServer>([&cmd](std::string cmdStr) ->std::string{
    //     return cmd.execute(cmdStr);
    // });
    Daemon(false, false);
    // 1. 计算模块
    calculator mycal;
    // 2. 解析模块
    Parse myparse([&mycal](const Request &req)
                  { return mycal.execute(req); });

    // 3.通信模块
    // 只负责IO
    std::unique_ptr<tcpServer> tsvr = std::make_unique<tcpServer>([&myparse](std::string &package)
                                                                  { return myparse.Entrance(package); });
    tsvr->initServer();
    tsvr->start();
    return 0;
}